<template>
	<view class="jf-picker__popup" v-if="props.show">
		<view class="jf-picker__popup-container">
			<view class="jf-picker__popup-top">
				<view class="jf-picker__popup-top-btn jf-picker__popup-top-cancel" @click="cancel()">{{props.cancelText}}</view>
				<view class="jf-picker__popup-top-title">{{props.title}}</view>
				<view class="jf-picker__popup-top-btn jf-picker__popup-top-confirm" @click="confirm()">{{props.confirmText}}</view>
			</view>
			<picker-view
				mask-style="font-size: 28rpx;color: #B9BFCB;font-weight: 400;border: none;height: 88rpx !important;line-height: 88rpx !important;"
				indicator-style="text-align: center;font-size: 32rpx;color: #141B24;font-weight: 400;height: 88rpx !important;line-height: 88rpx !important;"
				indicator-class="jf-picker__popup-indicator"
				:disabled="props.disabled"
				@change="change"
				@pickstart="pickstart"
				@pickend="pickend"
				:value="data.value"
				class="jf-picker__popup-content"
			>
				<picker-view-column v-for="(items,indexs) in data.range" :key="indexs" class="jf-picker__popup-column">
					<view class="jf-picker__popup-item" v-for="(item,index) in items" :key="index">{{item.label}}</view>
				</picker-view-column>
			</picker-view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	import { reactive, watch, onMounted, watchEffect } from 'vue';
	
	interface rangeItem{
		label: string
		value: string | number
	}
	interface Result{
		values: string[] | number[] | string | number
		rows: rangeItem | rangeItem[]
		indexs: number | number[]
		labels: string
	}
	
	const props = withDefaults(defineProps<{
		show?: boolean
		mode?: 'date' | 'selector' | 'multiSelector' | 'time' | 'datetime'
		modelValue?: string | number | number[] | string[]
		label?: string[] | string
		range?: rangeItem[] | rangeItem[][]
		disabled?: boolean
		start?: string
		end?: string
		fields?: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'
		cancelText?: string
		confirmText?: string
		title?: string
		units?: string[]
	}>(),{
		show: false,
		mode: 'selector',
		modelValue: undefined,
		label: "",
		range: () => [],
		disabled: false,
		start: undefined,
		end: undefined,
		fields: 'day',
		cancelText: '取消',
		confirmText: '确定',
		title: '',
		units: () => []
	})
	const emits = defineEmits<{
		(e: 'update:modelValue', value: string[] | number[] | string | number):void
		(e: 'update:show', show: boolean):void
		(e: 'update:label', label: string):void
		(e: 'confirm', result:Result ):void
		(e: 'cancel'):void
		(e: 'change', value: string[] | number[]):void
		(e: 'pickstart', eventhandle: any):void
		(e: 'pickend', eventhandle:any):void
	}>()
	const data = reactive({
		range: [],
		value: [],
		date: new Date()
	})
	
	const getYears = ():rangeItem[] =>{
		const years:rangeItem[] = []
		const nowYear = new Date(data.date).getFullYear()
		let startYear = 1970
		let endYear = 2200
		if(props.start){
			const start = new Date(props.start)
			startYear = start.getFullYear()
		}
		if(props.end){
			const end = new Date(props.end)
			endYear = end.getFullYear()
		}
		const unit = props.units[0] || ''
		for(let i = startYear;i <= endYear;i++){
			years.push({ label: i + unit, value: i})
			if(i === nowYear){
				data.value.push(years.length - 1)
			}
		}
		return years
	}
	const getMonths = ():rangeItem[] =>{
		const months:rangeItem[] = []
		const nowYear = data.range[0][data.value[0]].value
		const nowMonth = new Date(data.date).getMonth() + 1
		let startMonth = 1
		let endMonth = 12
		if(props.start){
			const start = new Date(props.start)
			if(start.getFullYear() === nowYear){
				startMonth = start.getMinutes() + 1
			}else if(start.getFullYear() > nowYear){
				endMonth = 1
			}
		}
		if(props.end){
			const end = new Date(props.end)
			if(end.getFullYear() === nowYear){
				endMonth = end.getMinutes() + 1
			}else if(end.getFullYear() > nowYear){
				endMonth = 1
			}
		}
		const unit = props.units[1] || ''
		for(let i = startMonth;i <= endMonth;i++){
			months.push({ label: i + unit, value: i})
			if(i === nowMonth){
				data.value.push(months.length - 1)
			}
		}
		return months
	}
	const getDates = ():rangeItem[] =>{
		const dates:rangeItem[] = []
		const nowYear = data.range[0][data.value[0]].value
		const nowMonth = data.range[1][data.value[1]].value
		const nowDate = new Date(data.date).getDate()
		let startDate = 1
		let endDate = new Date(nowYear, nowMonth, 0).getDate()
		// if(props.start){
		// 	const start = new Date(props.start)
		// 	if(start.getFullYear() === nowYear){
		// 		startMonth = start.getMinutes() + 1
		// 	}else if(start.getFullYear() > nowYear){
		// 		endMonth = 1
		// 	}
		// }
		// if(props.end){
		// 	const end = new Date(props.end)
		// 	if(end.getFullYear() === nowYear){
		// 		endMonth = end.getMinutes() + 1
		// 	}else if(end.getFullYear() > nowYear){
		// 		endMonth = 1
		// 	}
		// }
		const unit = props.units[2] || ''
		for(let i = startDate;i <= endDate;i++){
			dates.push({ label: i + unit, value: i})
			if(i === nowDate){
				data.value.push(dates.length - 1)
			}
		}
		return dates
	}
	const getNowDate = ():string =>{
		if(props.modelValue){
			return props.modelValue
		}else{
			if((props.mode === 'date' || props.mode === 'datetime' || props.mode === 'time') && !data.value){
				const date = new Date();
				if(props.fields === "year"){
					return date.getFullYear().toString()
				}else if(props.fields === 'month'){
					return [date.getFullYear(), fillZero(date.getMonth() + 1)].join("/")
				}else if(props.fields === 'day'){
					return [date.getFullYear(), fillZero(date.getMonth() + 1), fillZero(date.getDate())].join("/")
				}else if(props.fields === 'hour' && props.mode === 'datetime'){
					return [date.getFullYear(), fillZero(date.getMonth() + 1), fillZero(date.getDate())].join("/") + " " + [fillZero(date.getHours())]
				}else if(props.fields === 'minute' && props.mode === 'datetime'){
					return [date.getFullYear(), fillZero(date.getMonth() + 1), fillZero(date.getDate())].join("/") + " " + [fillZero(date.getHours()), fillZero(date.getMinutes())].join(":")
				}else if(props.fields === 'second' && props.mode === 'datetime'){
					return [date.getFullYear(), fillZero(date.getMonth() + 1), fillZero(date.getDate())].join("/") + " " + [fillZero(date.getHours()), fillZero(date.getMinutes()), fillZero(date.getSeconds())].join(":")
				}else if(props.fields === 'hour' && props.mode === 'time'){
					return fillZero(date.getHours())
				}else if(props.fields === 'minute' && props.mode === 'time'){
					return [fillZero(date.getHours()), fillZero(date.getMinutes())].join(":")
				}else if(props.fields === 'second' && props.mode === 'time'){
					return [fillZero(date.getHours()), fillZero(date.getMinutes()), fillZero(date.getSeconds())].join(":")
				}
			}
		}
	}
	const resetRange = () =>{
		if(props.mode === 'selector'){
			data.range = [<rangeItem[]>props.range];
		}else if(props.mode === 'multiSelector'){
			data.range = <rangeItem[][]>props.range;
		}else if(props.mode === 'date' || props.mode === 'datetime'){
			data.range = [];
			if(props.modelValue)data.date = new Date(props.modelValue)
			data.range.push(getYears());
			if(props.fields === 'month' || props.fields === 'day'){
				data.range.push(getMonths());
			}
			if(props.fields === 'day'){
				data.range.push(getDates());
			}
		}
	}
	const pickstart = (eventhandle:any):void =>{
		emits('pickstart' ,eventhandle)
	}
	const pickend = (eventhandle:any):void =>{
		emits('pickend' ,eventhandle)
	}
	const change = (result:any):void =>{
		data.value = result.detail.value;
		resetRange()
		emits('change', data.value)
	}
	const cancel = ():void =>{
		emits('update:show', false)
		emits('cancel')
	}
	const confirm = ():void =>{
		let values = null
		let labels = undefined;
		let rows = null;
		if(props.mode === "selector"){
			values = data.range[0][data.value[0]].value
			labels = data.range[0][data.value[0]].label
			rows = data.range[0][data.value[0]]
		}else if(props.mode === "multiSelector"){
			values = []
			labels = []
			rows = []
			for(let index in data.value){
				values.push(data.range[index][data.value[index]].value)
				labels.push(data.range[index][data.value[index]].label)
				rows.push(data.range[index][data.value[index]])
			}
		}else if(props.mode === "date"){
			rows = []
			if(props.fields === "day"){
				values = [data.range[0][data.value[0]].value, fillZero(data.range[1][data.value[1]].value), fillZero(data.range[2][data.value[2]].value)].join("/")
				rows = [data.range[0][data.value[0]], data.range[1][data.value[1]], data.range[2][data.value[2]]]
			}else if(props.fields === "month"){
				values = [data.range[0][data.value[0]].value, fillZero(data.range[0][data.value[1]].value)].join("/")
				rows = [data.range[0][data.value[0]], data.range[1][data.value[1]]]
			}else if(props.fields === "year"){
				values = data.range[0][data.value[0]].value.toString()
				rows = [data.range[0][data.value[0]]]
			}
			labels = values
		}else if(props.mode === "time"){
			values = [fillZero(data.range[0][data.value[0]].value), fillZero(data.range[1][data.value[1]].value), fillZero(data.range[2][data.value[2]].value)].join(":")
			labels = values
			rows = [data.range[0][data.value[0]], data.range[1][data.value[1]], data.range[2][data.value[2]]]
		}else if(props.mode === "datetime"){
			values = [data.range[0][data.value[0]].value, fillZero(data.range[1][data.value[1]].value), fillZero(data.range[2][data.value[2]].value)].join("/") + " " + [fillZero(data.range[3][data.value[3]].value), fillZero(data.range[4][data.value[4]].value), fillZero(data.range[5][data.value[5]].value)].join(":")
			labels = values
			rows = [data.range[0][data.value[0]], data.range[1][data.value[1]], data.range[2][data.value[2]], data.range[3][data.value[3]], data.range[4][data.value[4]], data.range[5][data.value[5]]]
		}
		emits('update:modelValue', values)
		emits('update:label', labels)
		emits('update:show', false)
		emits('confirm', { values, labels, rows, indexs: data.value })
	}
	const fillZero = (value:number | string):string =>{
		return value < 10 ? ('0' + value) : value.toString()
	}
	
	watchEffect(() =>{
		if(!Array.isArray(props.range[0])){
			data.range = [<rangeItem[]>props.range];
		}else{
			data.range = <rangeItem[][]>props.range;
		}
	})
	watch(() => props.show,(nVal:boolean)=>{
		if(nVal){
			if(props.mode === "selector"){
				data.value = []
				let index = props.range.findIndex(item => props.modelValue === item.value);
				if(index === -1) index = 0
				data.value.push(index)
			}else if(props.mode === "multiSelector"){
				data.value = []
				if(Array.isArray(props.modelValue) && props.modelValue.length === props.range.length){
					for(let indexs in props.range){
						let index = props.range[indexs].findIndex(item => props.modelValue === item.value);
						if(index === -1) index = 0
						data.value.push(index)
					}
				}
			}else if(props.mode === "date" || props.mode === "datetime" || props.mode === "time"){
				if(typeof props.modelValue === 'string'){
					data.date = new Date(props.modelValue)
					resetRange()
				}
			}
		}
	},{
		deep: true
	})
	onMounted(()=>{
		resetRange()
	})
</script>

<style lang="scss">
	.jf-picker{
		width: 654rpx;
		height: 144rpx;
		margin-left: 48rpx;
		.jf-picker__background{
			width: 654rpx;
			height: 96rpx;
			border-radius: 24rpx;
			padding: 2rpx;
			background: #F2F4F6;
			box-sizing: border-box;
			.jf-picker__content{
				
			}
			.jf-picker__box{
				display: flex;
				flex-direction: row;
				align-items: center;
				width: 650rpx;
				height: 92rpx;
				background: #F2F4F6;
				border-radius: 24rpx;
			}
			&.active{
				background: var(--background);
				.jf-picker__box{
					background: #ffffff;
				}
			}
			&.danger{
				background: #F40002;
			}
		}
	}
	.jf-picker__popup{
		--popup-width: 100vw;
		position: fixed;
		z-index: 998;
		left: 0;
		top: 0;
		width: var(--popup-width);
		height: 100vh;
		background: rgba(0, 0, 0, 0.4);
		.jf-picker__popup-container{
			position: absolute;
			bottom: 0;
			left: 0;
			--popup-height: 660rpx;
			--popup-top-height: 144rpx;
			width: var(--popup-width);
			height: var(--popup-height);
			border-radius: 48rpx 48rpx 0 0;
			background: #ffffff;
			.jf-picker__popup-top{
				position: relative;
				display: flex;
				flex-direction: row;
				align-items: center;
				justify-content: center;
				width: var(--popup-width);
				height: var(--popup-top-height);
				border-bottom: 2rpx solid #ECECEC;
				.jf-picker__popup-top-btn{
					position: absolute;
					top: 12rpx;
					font-size: 28rpx;
					color: #0069FF;
					font-weight: 400;
					line-height: 40rpx;
					padding: 40rpx;
					&.jf-picker__popup-top-cancel{
						left: 0;
					}
					&.jf-picker__popup-top-confirm{
						right: 0;
					}
				}
				.jf-picker__popup-top-title{
					padding: 0 50rpx;
					font-size: 32rpx;
					font-weight: 500;
					color: #161D26;
					line-height: 40rpx;
					box-sizing: border-box;
				}
			}
			.jf-picker__popup-content{
				position: relative;
				width: 686rpx;
				height: calc(var(--popup-height) - var(--popup-top-height));
				margin-left: 32rpx;
				&::before{
					position: absolute;
					top: 50%;
					transform: translateY(-50%);
					content: "";
					width: 100%;
					height: 88rpx;
					background: #F2F4F6;
					border-radius: 16rpx;
				}
				.jf-picker__popup-item{
					position: relative;
					z-index: 100;
					line-height: 88rpx !important;
					text-align: center;
				}
			}
		}
	}
	::v-deep .jf-picker__popup-indicator{
		height: 88rpx;
		&::after,&::before{
			border: none !important;
		}
	}
</style>
